// 声明
trait Contains<A, B> {
    fn container(&self, a: &A, b: &B) -> bool; // 显式要求 A B
    fn first(&self) -> i32; // 未显式要求 A B
    fn last(&self) -> i32;
}

struct Container(i32, i32);
// 不使用关联类型
impl Contains<i32, i32> for Container {
    fn container(&self, a: &i32, b: &i32) -> bool {
        (&self.0 == a) && (&self.1 == b)
    }
    fn first(&self) -> i32 {
        self.0
    }
    fn last(&self) -> i32 {
        self.1
    }
}

fn diffrence<A, B, C>(container: &C) -> i32
where
    C: Contains<A, B>, // 必须指定, 否则 last, first 无法执行: consider restricting the type parameter to satisfy the trait bound: ` where C: Iterator`
{
    &container.last() - &container.first()
}

// 使用关联类型
trait ContainsAB {
    // 在这里定义可以被方法使用的泛型类型。
    type A;
    type B;
    // self在方法参数中代表这个方法的接收对象，在模块中代表本模块的作用域。
    // Self是trait与impl代码块中的语法糖，用来代表当前方法的接收类型，支持泛型。
    // fn contains(&self, _: &self::A, _: &self::B) -> bool;
    fn contains(&self, a: &Self::A, b: &Self::B) -> bool;
    fn first(&self) -> i32;
    fn last(&self) -> i32;
}
impl ContainsAB for Container {
    type A = i32;
    type B = i32;
    fn contains(&self, a: &Self::A, b: &Self::B) -> bool {
        (&self.0 == a) && (&self.1 == b)
    }
    fn first(&self) -> i32 {
        self.0
    }
    fn last(&self) -> i32 {
        self.1
    }
}

// 只能实现一个 trait
// impl ContainsAB for Container {
//     type A = f32;
//     type B = f32;
//     fn contains(&self, a: &Self::A, b: &Self::B) -> bool {
//         (&self.0 == a) && (&self.1 == b)
//     }
//     fn first(&self) -> f32 {
//         self.0
//     }
//     fn last(&self) -> f32 {
//         self.1
//     }
// }

fn diffrence_ab<C: ContainsAB>(container: &C) -> i32 {
    // container.contains(3, 4)
    container.last() - container.first()
}

fn main() {
    println!("关联类型");

    let container = Container(1, 4);
    println!("不使用关联类型: {}", diffrence(&container));
    println!("使用关联类型: {}", diffrence_ab(&container));
}
